package com.thirteenClassicsServer.service.impl;

import com.thirteenClassics.async.EntryServiceAsync;
import com.thirteenClassics.async.ThreadPoolManager;
import com.thirteenClassics.cache.JdbSentenceCache;
import com.thirteenClassics.context.BaseContext;
import com.thirteenClassics.convert.OperationHistoryConvertMapper;
import com.thirteenClassics.convert.SentenceConvertMapper;
import com.thirteenClassics.dto.*;
import com.thirteenClassics.entity.*;
import com.thirteenClassics.enumeration.BookTypeFlagEnum;
import com.thirteenClassics.exception.BaseException;
import com.thirteenClassics.result.PageResult;
import com.thirteenClassics.vo.EntryCatalogQueryVO;
import com.thirteenClassics.vo.SentenceVO;
import com.thirteenClassicsServer.cacheService.BookServiceCache;
import com.thirteenClassicsServer.cacheService.UserServiceCache;
import com.thirteenClassicsServer.common.EntryCommonService;
import com.thirteenClassicsServer.mapper.*;
import com.thirteenClassicsServer.service.IEntryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.thirteenClassicsServer.service.impl.XmlParseService.toGetTableName;

@Service
@Slf4j

public class EntryServiceImpl implements IEntryService {
    @Resource
    private EntryServiceAsync entryServiceAsync;
    @Resource
    private EntryMapper entryMapper;
    @Resource
    private BookMapper bookMapper;
    @Resource
    private UserMapper userMapper;
    @Autowired
    private UserServiceImpl userService;
    @Resource
    private SentenceMapper sentenceMapper;
    @Resource
    private PictureMapper pictureMapper;
    @Resource
    private CatalogBookMapper catalogBookMapper;
    @Resource
    private SentenceLinkMapper sentenceLinkMapper;
    @Resource
    private OperationHistoryMapper operationHistoryMapper;
    @Resource
    private OperationHistoryConvertMapper operationHistoryConvertMapper;
    @Autowired
    private EntryCommonService commonService;
    @Resource
    private JdbSentenceCache jdbSentenceCache;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private BookServiceCache bookServiceCache;
    @Autowired
    private UserServiceCache userServiceCache;


    @Override
    public PageResult pageQuery2(EntryPageQueryDTO entryPageQueryDTO){
        entryPageQueryDTO.setJdbFlag(BookTypeFlagEnum.JDB.getCode());
        List<Book> books = entryMapper.AllEntryQuery(entryPageQueryDTO);
        List<BookDto> bookDtoList = new ArrayList<>();
        for (Book book : books) {
            BookDto bookDto = convertToBookDto(book);
            setFlagBasedOnLanguage(bookDto, book.getBookLang());
            setOperationHistory(bookDto, book.getId());
            setBookLanguageList(bookDto, book.getBookLang());
            bookDtoList.add(bookDto);
        }
        List<BookDto> allBooks = sortBooksByFlag(bookDtoList);
        //内存分页
        int startIndex = (entryPageQueryDTO.getPage()-1) * entryPageQueryDTO.getPageSize();
        if(startIndex >= allBooks.size()) {
            allBooks.clear();
        }
        int endIndex = Math.min(startIndex + entryPageQueryDTO.getPageSize(), allBooks.size());
        return new PageResult(allBooks.size(), allBooks.subList(startIndex, endIndex));

    }

    public List<BookDto> sortBooksByFlag(List<BookDto> bookDtoList) {
        Comparator<BookDto> comparator = Comparator.comparing(BookDto::getFlag, Comparator.reverseOrder())
                .thenComparing(bookDto -> Optional.ofNullable(bookDto.getBookEntryTime()).orElse(LocalDateTime.MIN), Comparator.reverseOrder());

        return bookDtoList.stream()
                .sorted(comparator)
                .collect(Collectors.toList());
    }



    private BookDto convertToBookDto(Book book) {
        BookDto bookDto = new BookDto();
        BeanUtils.copyProperties(book, bookDto);
        return bookDto;
    }

    private void setFlagBasedOnLanguage(BookDto bookDto, String bookLang) {
        bookDto.setFlag(BookServiceImpl.judge(bookLang, BaseContext.getCurrentLang()) ? 1L : 0L);
    }

    private void setOperationHistory(BookDto bookDto, Long bookId) {
        OperationHistory operationHistory = new OperationHistory();
        operationHistory.setBookId(bookId);
        operationHistory.setUserId(BaseContext.getCurrentId());
        operationHistory.setAction(1L);

        OperationHistory operationHistory1 = operationHistoryMapper.selectIndex(operationHistory);
        if (operationHistory1 != null) {
            bookDto.setIndex(operationHistory1.getIndex());
            bookDto.setSentenceIndex(operationHistory1.getSentenceIndex());
            bookDto.setParagraphIndex(operationHistory1.getParagraphIndex());
        }
    }

    private void setBookLanguageList(BookDto bookDto, String bookLang) {
        List<String> characterList = Arrays.asList(bookLang.trim().split(" "));
        bookDto.setBookLang(new ArrayList<>(characterList));
    }


    public int[] parseNumbers(String input) {
        if (input.length() == 0) {
            return new int[0];
        }
        String[] parts = input.split("[,，]"); // 按英文逗号或中文逗号分割字符串
        int[] numbers = new int[parts.length];
        for (int i = 0; i < parts.length; i++) {
            numbers[i] = Integer.parseInt(parts[i]); // 转换成整数
        }
        return numbers;
    }


    @Override
    public List<SentenceVO> jdbContentForChapter(JdbContentForChapterDTO jdbContentForChapterDTO) {
        return jdbSentenceCache.jdbContentForChapter(jdbContentForChapterDTO);
    }


    @Override
    @Cacheable(value = "EntryCache", key = "'Entry-' + #entryCatalogQueryDTO.bookId + '-' + #entryCatalogQueryDTO"
            + ".bookName + '-' + #entryCatalogQueryDTO.index + '-' + #entryCatalogQueryDTO.sentenceIndex + '-' + "
            + "#entryCatalogQueryDTO.paragraphIndex")
    public EntryCatalogQueryVO selectCatalogAndAll(EntryCatalogQueryDTO entryCatalogQueryDTO) {
        return commonService.selectCatalogAndAllCommon(entryCatalogQueryDTO);
    }

    @Override
    @Cacheable(value = "EntryCacheNew", key = "'EntryNew-' + #entryCatalogQueryDTO.bookId + '-' + #entryCatalogQueryDTO"
            + ".bookName + '-' + #entryCatalogQueryDTO.index + '-' + #entryCatalogQueryDTO.sentenceIndex + '-' + "
            + "#entryCatalogQueryDTO.paragraphIndex")
    public EntryCatalogQueryVO selectCatalogAndAllNew(EntryCatalogQueryDTO entryCatalogQueryDTO) {
        return commonService.selectCatalogAndAllCommonNew(entryCatalogQueryDTO);
    }

    @Override
    public synchronized void save(EntryDTO entryDto) {
        // 清除缓存
        entryServiceAsync.evictEntryCache(entryDto);
        entryServiceAsync.evictEntryCacheNew(entryDto);
        try {
            Book book = bookServiceCache.selectMinorityBookByEntryId(entryDto.getEntryId());
            String bookName = book.getBookName();
            String userName = userServiceCache.getUserNameById(BaseContext.getCurrentId());

            // 异步任务1：更新EntryTime和Name
            CompletableFuture<Void> updateEntryTimeAndNameTask = CompletableFuture.runAsync(() ->
                    bookServiceCache.updateEntryTimeAndNameAsync(book.getId(), userName), ThreadPoolManager.getExecutorService());

            // 异步任务2：处理Sentence和SentenceLink
            CompletableFuture<Void> handleSentenceTask = CompletableFuture.runAsync(() -> {
                Sentence sentenceOne = sentenceMapper.selectOneSentence(entryDto, toGetTableName(bookName));
                Sentence sentence = SentenceConvertMapper.INSTANCE.entryDtoToSentenceWithDefaults(entryDto, userName);

                if (sentenceOne != null) {
                    sentence.setSentenceId(sentenceOne.getSentenceId());
                    sentenceMapper.updateSentence(sentence, toGetTableName(bookName));
                    sentenceLinkMapper.delete(sentenceOne.getSentenceId(), book.getId());
                } else {
                    sentenceMapper.insert(sentence, toGetTableName(bookName));
                }
                List<SentenceLink> sentenceLinkList = new ArrayList<>();
                Optional.ofNullable(entryDto.getSentenceIdJd()).ifPresent(lists ->
                        lists.forEach(sentenceJd -> {
                            SentenceLink sentenceLink = new SentenceLink();
                            sentenceLink.setSentenceId(sentence.getSentenceId());
                            sentenceLink.setSentencejdbId(sentenceJd);
                            sentenceLink.setSentenceIds(entryDto.getSentenceIds());
                            sentenceLink.setBookName(entryDto.getBookName());
                            sentenceLink.setBookId(book.getId());
                            sentenceLinkList.add(sentenceLink);
                        })
                );
                if (!sentenceLinkList.isEmpty()) {
                    sentenceLinkMapper.insertBatch(sentenceLinkList);
                }
            }, ThreadPoolManager.getExecutorService());

            // 异步任务3：更新少语的句子数量
            CompletableFuture<Void> updateSentenceNumTask = CompletableFuture.runAsync(() -> {
                Long sentenceNum = catalogBookMapper.selectMinoritySentenceNumById(entryDto.getEntryId());
                if (sentenceNum == null) {
                    sentenceNum = 0L;
                }
                catalogBookMapper.updateMinoritySentenceNum(Math.max(sentenceNum, entryDto.getSentenceIds()), entryDto.getEntryId());
            }, ThreadPoolManager.getExecutorService());
            // 等待所有任务完成
            CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(updateEntryTimeAndNameTask, handleSentenceTask, updateSentenceNumTask);

            combinedFuture.join();  // 等待所有任务完成

            // 刷新缓存
            ThreadPoolManager.getExecutorService().submit(() -> {
                entryServiceAsync.selectCatalogAndAllFlashCache(EntryCatalogQueryDTO.builder()
                        .index(entryDto.getIndex())
                        .bookName(entryDto.getBookName())
                        .bookId(entryDto.getBookId())
                        .paragraphIndex(entryDto.getParagraphIndex())
                        .sentenceIndex(entryDto.getSentenceIndex())
                        .build());
                entryServiceAsync.selectCatalogAndAllFlashCacheNew(EntryCatalogQueryDTO.builder()
                        .index(entryDto.getIndex())
                        .bookName(entryDto.getBookName())
                        .bookId(entryDto.getBookId())
                        .paragraphIndex(entryDto.getParagraphIndex())
                        .sentenceIndex(entryDto.getSentenceIndex())
                        .build());
            });
        } catch (Exception e) {
            throw new BaseException("保存失败", e);
        }
    }


//    @Override
//    @Transactional
//    @CacheEvict(value = "EntryCache", key = "'Entry-' + #entryDto.bookId + '-' + #entryDto.bookName + '-' + #entryDto"
//            + ".index + '-' + #entryDto.sentenceIndex + '-' + #entryDto.paragraphIndex")
//    public void save(EntryDTO entryDto) {
//
//        try {
//            Book book = bookServiceCache.selectMinorityBookByEntryId(entryDto.getEntryId());
//            String bookName = book.getBookName();
//            String userName = userServiceCache.getUserNameById(BaseContext.getCurrentId());
//            bookServiceCache.updateEntryTimeAndNameAsync(book.getId(), userName);
//
//            Sentence sentenceOne = sentenceMapper.selectOneSentence(entryDto, toGetTableName(bookName));
//            Sentence sentence = SentenceConvertMapper.INSTANCE.entryDtoToSentenceWithDefaults(entryDto, userName);
//            if (sentenceOne != null) {
//                sentence.setSentenceId(sentenceOne.getSentenceId());
//                sentenceMapper.updateSentence(sentence, toGetTableName(bookName));
//                if(sentenceOne.getSentenceId() != 0){
//                    sentenceLinkMapper.delete(sentenceOne.getSentenceId(), book.getId());
//                }
//            }else{
//                sentenceMapper.insert(sentence, toGetTableName(bookName));
//            }
//
//
//            List<SentenceLink> sentenceLinkList = new ArrayList<>();
//
//            Optional.ofNullable(entryDto.getSentenceIdJd())
//                    .ifPresent(lists -> lists.forEach(sentencejd -> {
//                        SentenceLink sentenceLink = new SentenceLink();
//                        sentenceLink.setSentenceId(sentence.getSentenceId());
//                        sentenceLink.setSentencejdbId(sentencejd);
//                        sentenceLink.setSentenceIds(entryDto.getSentenceIds());
//                        sentenceLink.setBookName(entryDto.getBookName());
//                        sentenceLink.setBookId(book.getId());
//                        sentenceLinkList.add(sentenceLink);
//                    }));
//
//            // 批量插入
//            if (!sentenceLinkList.isEmpty()) {
//                sentenceLinkMapper.insertBatch(sentenceLinkList);
//            }
//
//            //保存少语的句子数量
//            Long sentenceNum = catalogBookMapper.selectMinoritySentenceNumById(entryDto.getEntryId());
//            if (sentenceNum == null) {
//                sentenceNum = 0L;
//            }
//            catalogBookMapper.updateMinoritySentenceNum(Math.max(sentenceNum, entryDto.getSentenceIds()),
//                    entryDto.getEntryId());
//        }catch (Exception e){
//            throw new BaseException("保存失败");
//        }
//
//
//        entryServiceAsync.selectCatalogAndAllFlashCache(EntryCatalogQueryDTO.builder()
//                .index(entryDto.getIndex())
//                .bookName(entryDto.getBookName())
//                .bookId(entryDto.getBookId())
//                .paragraphIndex(entryDto.getParagraphIndex())
//                .sentenceIndex(entryDto.getSentenceIndex())
//                .build());
//    }

    @Override
    public void saveOperationHistory(EntryCatalogQueryDTO entryCatalogQueryDTO, Long action) {
        // 直接调用异步保存操作
        saveOperationHistoryAsync(entryCatalogQueryDTO, action);
    }

    private void saveOperationHistoryAsync(EntryCatalogQueryDTO entryCatalogQueryDTO, Long action) {

        // 获取当前 ID
        Long currentId = BaseContext.getCurrentId();
        ThreadPoolManager.getExecutorService().submit(() -> {
            // 转换 DTO 为 OperationHistory 对象
            OperationHistory operationHistory =
                    operationHistoryConvertMapper.convert2OperationHistory(entryCatalogQueryDTO, action, currentId);
            // 查询旧的操作记录
            OperationHistory operationHistoryOld = operationHistoryMapper.selectIndex(operationHistory);
            // 根据是否存在更新或插入操作历史记录
            if (operationHistoryOld != null) {
                operationHistory.setId(operationHistoryOld.getId());
                operationHistoryMapper.update(operationHistory);
                log.info("更新操作记录成功，ID: {}", operationHistoryOld.getId());
            } else {
                operationHistoryMapper.insert(operationHistory);
                log.info("插入操作记录成功，ID: {}", operationHistory.getId());
            }
        });
    }


    @Override
    public Entry selectEntryBook(Entry entry) {
        return entryMapper.selectEntryBook(entry);
    }

}
